package com.github.wj.security.server.aspect;
import com.github.wj.security.server.annotation.WebLoggerWriter;
import com.github.wj.security.server.entity.TBsdtLogger;
import com.github.wj.security.server.service.TLoggerManageService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.security.core.context.SecurityContextImpl;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.HandlerMapping;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.Map;

/**
 * 日志记录功能
 * Created by wangj on 2017/7/12.
 */
@Aspect
@Component
public class WebRequestLoggerAspect {

    private static final Logger LOG= LoggerFactory.getLogger(WebRequestLoggerAspect.class);

    private ThreadLocal<TBsdtLogger> tlocal = new ThreadLocal<TBsdtLogger>();

    @Autowired
    private TLoggerManageService service;

    @Order(5)
    @Before("@annotation(webLoggerWriter)")
    public void doLoggerBefore(JoinPoint point, WebLoggerWriter webLoggerWriter){
        try {

            long beginTime = System.currentTimeMillis();
            // 接收到请求，记录请求内容
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = attributes.getRequest();
            String beanName = point.getSignature().getDeclaringTypeName();
            String methodName = point.getSignature().getName();
            String uri = request.getRequestURI();
            String remoteAddr = getIpAddr(request);
            //String sessionId = request.getSession().getId(); session
            SecurityContextImpl securityContextImpl = (SecurityContextImpl) request.getSession().getAttribute("SPRING_SECURITY_CONTEXT");
            String user=securityContextImpl.getAuthentication().getName();
            String method = request.getMethod();
            String params = "";
            if ("POST".equals(method)) {
                Object[] paramsArray = point.getArgs();
                params = argsArrayToString(paramsArray);
            } else {
                Map<?, ?> paramsMap = (Map<?, ?>) request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
                params = paramsMap.toString();
            }

            LOG.debug("uri=" + uri + "; beanName=" + beanName + "; remoteAddr=" + remoteAddr + "; user=" + user
                    + "; methodName=" + methodName + "; params=" + params);

            TBsdtLogger optLog = new TBsdtLogger();
            optLog.setBeanName(beanName);
            optLog.setLoginid(user);
            optLog.setMethodName(methodName);
            optLog.setRemoteAddr(remoteAddr);
            optLog.setRequestUri(uri);
            optLog.setRequestDate(new Date());
            optLog.setBeginTime(beginTime);
            tlocal.set(optLog);

        } catch (Exception e) {
            LOG.error("***操作请求日志记录失败doBefore()***", e);
        }
    }

    @Order(5)
    @AfterReturning(pointcut = "@annotation(webLoggerWriter)",returning = "result")
    public void doLoggerAfter(WebLoggerWriter webLoggerWriter,Object result){
        try {
            // 处理完请求，返回内容
            TBsdtLogger optLog = tlocal.get();
            optLog.setResult(result.toString());
            long beginTime = optLog.getBeginTime();
            long requestTime = (System.currentTimeMillis() - beginTime) / 1000;
            optLog.setRequestTime(String.valueOf(requestTime));
            LOG.debug("请求耗时：" + optLog.getRequestTime() + "   **** "+ optLog.getMethodName());
            LOG.debug("RESPONSE : " + result);
            service.save(optLog);
        } catch (Exception e) {
            LOG.error("***doLoggerAfter()***", e);
        }
    }

    /**
     * 获取登录用户远程主机ip地址
     *
     * @param request
     * @return
     */
    private String getIpAddr(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

    /**
     * 请求参数拼装
     *
     * @param paramsArray
     * @return
     */
    private String argsArrayToString(Object[] paramsArray) {
        String params = "";
        if (paramsArray != null && paramsArray.length > 0) {
            /*for (int i = 0; i < paramsArray.length; i++) {
                Object jsonObj = JSON.toJSON(paramsArray[i]);
                params += jsonObj.toString() + " ";
            }*/
        }
        return params.trim();
    }
}
